﻿using System;
using System.Windows.Forms;


namespace BTSegWay
{
    
    public partial class DIYSMobile : Form
    {
        #region private members
        private DIYSCom _com;
        private DIYSValues _diys;
        #endregion

        /// <summary>
        /// Constructor
        /// </summary>
        public DIYSMobile()
        {
            InitializeComponent();

            InitDiys();
            InitCom();         
            InitUI();

            tabControl1.SelectedIndex = 2;
        
        }

        /// <summary>
        /// Inits DIYSValues - value container
        /// </summary>
        private void InitDiys()
        {
            _diys = new DIYSValues { KP = 24, KD = 2, KS = 1 };

            _diys.OnKSChanged += new DoubleDelegate(_diys_OnKSChanged);
            _diys.OnKDChanged += new DoubleDelegate(_diys_OnKDChanged);
            _diys.OnKPChanged += new DoubleDelegate(_diys_OnKPChanged);

            _diys.OnAccAngleChanged += new DoubleDelegate(_diys_OnAccAngleChanged);
            _diys.OnApproxAngleChanged += new DoubleDelegate(_diys_OnApproxAngleChanged);
            _diys.OnGyroAngleChanged += new DoubleDelegate(_diys_OnGyroAngleChanged);
            _diys.OnPWMChanged += new IntegerDelegate(_diys_OnPWMChanged);
            _diys.OnSteeringChanged += new IntegerDelegate(_diys_OnSteeringChanged);

        }

        /// <summary>
        /// Inits Communication to DIYS
        /// </summary>
        private void InitCom()
        {
            _com = new DIYSCom(_diys);
            _com.OnInputChanged += new StringDelegate(_com_OnInputChanged);
            _com.OnConnectionStatusChanged += new BooleanDelegate(_com_OnConnectionStatusChanged);

        }

        void _com_OnConnectionStatusChanged(bool value)
        {
            btnSend.Enabled = value;
            btnStream.Enabled = value;
            btnExtreme.Enabled = value;
            btnNormal.Enabled = value;
            btnBeginner.Enabled = value;
        }

        

        

        

        /// <summary>
        /// Inits UI elements, sets up eventlisteners
        /// </summary>
        void InitUI()
        {
            btnKD_dec.Click += new EventHandler(btnKD_dec_Click);
            btnKD_inc.Click += new EventHandler(btnKD_inc_Click);
            btnKP_dec.Click += new EventHandler(btnKP_dec_Click);
            btnKP_inc.Click += new EventHandler(btnKP_inc_Click);
            btnKS_dec.Click += new EventHandler(btnKS_dec_Click);
            btnKS_inc.Click += new EventHandler(btnKS_inc_Click);
            btnStream.Click += new EventHandler(btnStream_Click);
            btnSend.Click += new EventHandler(btnSend_Click);

            btnBeginner.Click += new EventHandler(btnBeginner_Click);
            btnNormal.Click += new EventHandler(btnNormal_Click);
            btnExtreme.Click += new EventHandler(btnExtreme_Click);

            lblKP.Text = _diys.KP.ToString();
            lblKD.Text = _diys.KD.ToString();
            lblKS.Text = _diys.KS.ToString();

            _com_OnConnectionStatusChanged(false);

            foreach (string s in _com.GetAvailibleCOMPorts())
            {
                cbCOM.Items.Add(s);
                if (s.Equals(_com.COMPort))
                    cbCOM.SelectedItem = s;
            }

            cbCOM.SelectedIndexChanged += new EventHandler(cbCOM_SelectedIndexChanged);


        }

        void btnExtreme_Click(object sender, EventArgs e)
        {
            _diys.ActiveProfile = _diys.Extreme;

            SendActiveProfile();

        }

        void btnNormal_Click(object sender, EventArgs e)
        {
            _diys.ActiveProfile = _diys.Normal;

            SendActiveProfile();
        }

        void btnBeginner_Click(object sender, EventArgs e)
        {
            _diys.ActiveProfile = _diys.Beginner;

            SendActiveProfile();
        }


        void SendActiveProfile()
        {
            int p = (int)(Math.Round(_diys.ActiveProfile.KP, 1) * 10);
            int d = (int)(Math.Round(_diys.ActiveProfile.KD, 1) * 10);
            int s = (int)(Math.Round(_diys.ActiveProfile.KS, 1) * 10);

            string command = "P" + p.ToString() + "~";
            command += "D" + d.ToString() + "~";
            command += "S" + s.ToString() + "~";

            _com.SendCommand(command);
        }
        
        /// <summary>
        /// Input from serial communication
        /// </summary>
        /// <param name="msg"></param>
        void _com_OnInputChanged(string msg)
        {
            string data = msg;
                SetText(data);
        }
        
        /// <summary>
        /// Threadsafe text-adder for textbox
        /// </summary>
        /// <param name="text">text to be displayed</param>
        void SetText(string text)
        {
            if (!InvokeRequired)
                tbText.Text = text + Environment.NewLine + tbText.Text;
            else
                Invoke(new StringDelegate(SetText), new object[] { text + tbText.Text });
        }

        /// <summary>
        /// New COM port selected
        /// </summary>
        void cbCOM_SelectedIndexChanged(object sender, EventArgs e)
        {
            _com.Stop();
            _com.COMPort = (string)(cbCOM.SelectedItem);
            
        }

        

        #region tweak button events
        void btnSend_Click(object sender, EventArgs e)
        {
            int p = (int)(Math.Round(Double.Parse(lblKP.Text), 1) * 10);
            int d = (int)(Math.Round(Double.Parse(lblKD.Text), 1) * 10);
            int s = (int)(Math.Round(Double.Parse(lblKS.Text), 1) * 10);

            string command = "P" + p.ToString()+"~";
            command += "D" + d.ToString() + "~";
            command += "S" + s.ToString() + "~";

            _com.SendCommand(command);
            
        }

        void btnKS_inc_Click(object sender, EventArgs e)
        {
            _diys.KS += 0.1;
        }

        void btnKS_dec_Click(object sender, EventArgs e)
        {
            _diys.KS -= 0.1;
        }

        void btnKP_inc_Click(object sender, EventArgs e)
        {
            _diys.KP += 0.1;
        }

        void btnKP_dec_Click(object sender, EventArgs e)
        {
            _diys.KP -= 0.1;
        }

        void btnKD_inc_Click(object sender, EventArgs e)
        {
            _diys.KD += 0.1;
        }

        void btnKD_dec_Click(object sender, EventArgs e)
        {
            _diys.KD -= 0.1;
        }

        #endregion

        void _diys_OnKPChanged(double value)
        {
            if (!InvokeRequired)
                lblKP.Text = _diys.KP.ToString();
            else
                Invoke(new DoubleDelegate(_diys_OnKPChanged), new object[] { value });
        }

        void _diys_OnKDChanged(double value)
        {
            if (!InvokeRequired)
                lblKD.Text = _diys.KD.ToString();
            else
                Invoke(new DoubleDelegate(_diys_OnKDChanged), new object[] { value });
        }

        void _diys_OnKSChanged(double value)
        {
            if (!InvokeRequired)
                lblKS.Text = _diys.KS.ToString();
            else
                Invoke(new DoubleDelegate(_diys_OnKSChanged), new object[] { value });
        }

        void _diys_OnSteeringChanged(int value)
        {
            if (!InvokeRequired)
                lblSteering.Text = _diys.Steering.ToString();
            else
                Invoke(new IntegerDelegate(_diys_OnSteeringChanged), new object[] { value });
        }

        void _diys_OnPWMChanged(int value)
        {
            if (!InvokeRequired)
                lblPWM.Text = _diys.PWM.ToString();
            else
                Invoke(new IntegerDelegate(_diys_OnPWMChanged), new object[] { value });
        }

        void _diys_OnGyroAngleChanged(double value)
        {
            if (!InvokeRequired)
                lblGyro.Text = _diys.GyroAnglePrSec.ToString();
            else
                Invoke(new DoubleDelegate(_diys_OnGyroAngleChanged), new object[] { value });
        }

        void _diys_OnApproxAngleChanged(double value)
        {
            if (!InvokeRequired)
                lblAngle.Text = _diys.ApproxAngle.ToString();
            else
                Invoke(new DoubleDelegate(_diys_OnApproxAngleChanged), new object[] { value });
        }

        void _diys_OnAccAngleChanged(double value)
        {
            if (!InvokeRequired)
                lblAcc.Text = _diys.AccAngle.ToString();
            else
                Invoke(new DoubleDelegate(_diys_OnAccAngleChanged), new object[] { value });
        }

        void btnStream_Click(object sender, EventArgs e)
        {
            _diys.StreamEnable = !_diys.StreamEnable;
            btnStream.Text = _diys.StreamEnable ? "Stop Stream" : "Start Stream";

            _com.SendCommand("T~");
        }


        private void menuItem1_Click(object sender, EventArgs e)
        {
            SetText("Connecting...");
            if (_com.Start())
               SetText("Serial Connected");
            else
                SetText("Error Connecting to serial");
        }

        private void menuItem2_Click(object sender, EventArgs e)
        {
            SetText("Disconnecting...");
            try
            {
                _com.Stop();
                SetText("Disconnected");
            }
            catch { }
            
            
        }
    }
}